package challenge;

import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by Tzachi on 18/10/2014.
 */
public class TangoInterview_Old {
    /**
     * Add one item of the product with ID productdId to the shopping cart for the user identified by sessionId
     * shoppingCarts contains all shopping carts for all users
     * a shopping cart for a user is represented as a Vector<Long>
     * - each Long represents an individual item in a cart
     * - duplicates are ok and indicate that multiple items of the same product are in the cart
     * <p>
     * this method must succeed
     * exit criteria is that you have added the product to the shopping cart associated with the user in a thread safe manner
     */

    public void addElement(String sessionId, Long productId, ConcurrentHashMap<String, Vector<Long>> shoppingCarts) {
        // it is for later usage in case someone deleted the vector associated with the sessionId during this call
        Vector<Long> ifEmptyVector = new Vector<>();
        ifEmptyVector.add(productId);

        // We need to figure out how to make sure that there is always an insertion or update
        // if results =  null -> there was no mapping to entry -> we entered a new vector with one product -> done
        // if results != null -> there was a previous entry -> results holds it now -> we need to update it
        Vector<Long> result;
        if ((result = shoppingCarts.putIfAbsent(sessionId, ifEmptyVector)) != null) {
            // at this point result cannot be null
            // We can be sure result holds the updated reference to the vector  by sessionId (until here)

            // thread safe due to vector -> updating the vector
            // if two threads reach here at the same time we can be sure both products will be added to cart
            result.add(productId);

            // we know that an update to an existing key was needed before
            // but before, but now we need to check again if deletion happened, to make sure that
            // there is always a correct state when this function call ends.

            // We will try to replace the previous vector with our new one
            // if is succeeds -> there were no deletion in between -> we successfully updated the value -> done
            // (technically, in this case replace did not do anything since we added to product to the cart on the previous line
            //  but we want to make sure that no one deleted it)
            shoppingCarts.replace(sessionId, result);
            // otherwise, the value was deleted between the if and here -> we will put the ifEmptyVector -> done
            shoppingCarts.putIfAbsent(sessionId, ifEmptyVector);
        }
    }
}
